/**
 * This software was produced for the U. S. Government
 * under Contract No. FA8721-09-C-0002, and is
 * subject to the Rights in Noncommercial Computer Software
 * and Noncommercial Computer Software Documentation Clause
 * (DFARS) 252.227-7014 (JUN 1995)
 * 
 * (c) 2009 The MITRE Corporation. All Rights Reserved.
 *
 * SPMIF to OPNET Translator
 * Author: ewalters
 * Created: 9:29:07 AM, Aug 23, 2007
 * MITRE Corporation
 */
package com.mitre.spmif2opnet.generation.ir;

import com.mitre.spmif2opnet.generation.OpnetGraphConverter;
import com.mitre.spmif2opnet.opnet.network.Attr;

/**
 * OPNET Link between Physical Nodes
 */
public class Link {
	
	/**
	 * Default port maximum 
	 */
	public static final int PORT_MAX = 4;
	
	/**
	 * Device name we are coming from
	 */
	private String _from_name;
	/**
	 * Device name we are going to
	 */
	private String _to_name;
	
	/**
	 * The ports we will be using
	 */
	private int _from_tx_port;
	private int _to_tx_port;
	private int _from_rx_port;
	private int _to_rx_port;
	
	/**
	 * Default constructor
	 * @param from
	 * @param to
	 */
	public Link(String from, String to) {
		_from_name = from;
		_to_name = to;
		_from_tx_port = _to_tx_port = _from_rx_port = _to_rx_port = 0;
	}
	
	/** 
	 * Validate port number and give feedback 
	 * @param port the port
	 */
	private void check_port(int port) {
		if (port >= PORT_MAX) {
			System.out.println("Attempting to set link port to greater number than default maximum!");
			System.out.println("NOTE: You may have to change the OPNET server process model to support this!");
		}
	}
	
	/**
	 * Set "from, transmit" port
	 * @param port the port
	 */
	public void setFromTxPort(int port) {
		check_port(port);
		_from_tx_port = port;
	}

	/**
	 * Set "to, transmit" port
	 * @param port the port
	 */
	public void setToTxPort(int port) {
		check_port(port);
		_to_tx_port = port;
	}

	/**
	 * Set "from, receive" port
	 * @param port the port
	 */
	public void setFromRxPort(int port) {
		check_port(port);
		_from_rx_port = port;
	}

	/**
	 * Set "to, receive" port
	 * @param port the port
	 */
	public void setToRxPort(int port) {
		check_port(port);
		_to_rx_port = port;
	}

	/**
	 * Turn the link into an OPNET Link
	 * @return the OPNET link
	 */
	public com.mitre.spmif2opnet.opnet.network.Link makeLink() {
		com.mitre.spmif2opnet.opnet.network.Link l = new com.mitre.spmif2opnet.opnet.network.Link();
		l.setName(_from_name + " <-> " + _to_name);
		l.setModel("10Gbps_Ethernet");
		l.setIgnoreQuestions("true");
		l.setMinMatchScore("strict matching");
		l.setSrcNode(_from_name);
		l.setDestNode(_to_name);
		l.setType("duplex");
		Attr a = OpnetGraphConverter.makeAttr("transmitter a", _from_name + ".eth_port_tx_" + _from_tx_port + "_0" );
		l.getCharacteristicOrAttrOrExtAttrOrPstateOrUiStatus().add(a);
		a = OpnetGraphConverter.makeAttr("receiver a", _from_name + ".eth_port_rx_" + _from_rx_port + "_0" ); 
		l.getCharacteristicOrAttrOrExtAttrOrPstateOrUiStatus().add(a);
		a = OpnetGraphConverter.makeAttr("transmitter b", _to_name + ".eth_port_tx_" + _to_tx_port + "_0" ); 
		l.getCharacteristicOrAttrOrExtAttrOrPstateOrUiStatus().add(a);
		a = OpnetGraphConverter.makeAttr("receiver b", _to_name + ".eth_port_rx_" + _to_rx_port + "_0" ); 
		l.getCharacteristicOrAttrOrExtAttrOrPstateOrUiStatus().add(a);
		return l;
	}
	
	/**
	 * For identity testing - override object
	 */
	public boolean equals(Object o) {
		if (!(o instanceof Link)) return false;
		Link l_other = (Link) o;
		return (this._from_name.equals(l_other._from_name) &&
				this._to_name.equals(l_other._to_name) &&
				(this._from_tx_port == l_other._from_tx_port) &&
				(this._from_rx_port == l_other._from_rx_port) &&
				(this._to_tx_port == l_other._to_tx_port) &&
				(this._to_rx_port == l_other._to_rx_port));
	}
	
	/**
	 * Reverse the direction of the link
	 * @return the reversed link
	 */
	public Link reverseLink() {
		Link l = new Link(_to_name, _from_name); 
		l.setFromTxPort(_to_tx_port);
		l.setFromRxPort(_to_rx_port);
		l.setToTxPort(_from_tx_port);
		l.setToRxPort(_from_rx_port);
		return l;
	}
	
	/**
	 * Get the source node
	 * @return the node
	 */
	public String getFromNode() {
		return _from_name;
	}
	
	/**
	 * Get the destination node
	 * @return the node
	 */
	public String getToNode() {
		return _to_name;
	}

	/**
	 * Dump the node as a string
	 */
	public String toString() {
		return _from_name + "_" + _from_tx_port + "_" + _from_rx_port + 
			" <-> " + _to_name + "_" + _to_tx_port + "_" + _to_rx_port;
	}
}
